home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
CUGUK
/
PC_LIBS
/
C045.ZIP
/
CPR.ARC
/
CPR.C
next >
Wrap
Text File
|
1988-05-30
|
47KB
|
1,315 lines
/*
CPR.C " Prints 'C' Files with Table of Contents "
" AND LOTS MORE "
Turbo C Version 1.0 or 1.5
Originally Written by :
Paul Breslin
Human Computing Resources Corp.
10 South Mary Street
Toronto, Ontario
Canada, M4Y 1P9
Modified by :
Lance E. Shepard Rick Wise Blake McBride
CCI & RIT CALCULON Corp. 3900 SW 52nd Ave. #803
Rochester, NY Rockville, MD 20850 Pembroke Park, FL 33023
John Stidd Dale Loftis
1570 Neston Way 3020 Yorba Linda #F-16
Los Altos, CA 94022 Fullerton, CA 92631
Special Notes:
A.) Table of Contents is held in Local Data Segment
So Compile This Program as SMALL (at Minimum).
*/
/* *************************************************************************
** Program Revision History
**
** By Dale Loftis
** 10-3-87 Changed WIDTH to 132, Tabs are now every 4, modified so
** that temporary file is deleted if control - break is hit,
** Improved the clarity of the instructions if no parmeters
** are given.
**
** 10-17-87 Changed so that no blank lines are printed in between structures.
**
** 11-06-87 Added -@ RESPONSE FILE feature since you couldn't fit all the
** filenames onto the command line, upto 400 files can be printed.
**
** Also adding the "Reading file # x of y" string and made program
** check the amount of free disk space before writing the files
** as the program would write the output file and run out of disk
** space and just put alot of junk on the disk.
**
** 11-08-87 Ver 1.0 Added -h HEADER FILE, -* "Print All 'C' Files,
** -x Extra Lines and Program Version Number
**
** 01-10-88 Ver 1.1 Added call to setvbuf() to speed up file access.
**
** 01-25-88 Ver 1.2 Added -t for option of just table of contents list
**
** 01-29-88 Ver 1.3 Fixed Bug. funcname () would not be put in Table of
** Contents because of space between funcname and ().
**
** 04-26-88 Ver 1.4 Added -p* option for starting page number and changed
** Table of Contents so File Date and Time Shown.
**
** 05-12-88 Ver 1.5 Added -q* option to print files by section number
** rather than by page number.
** Added -t- option to suppress the Table of Contents
*/
/* --------------------------------------------------------------------- */
/*
Include Files for Library Function Prototypes
*/
#include <stdio.h>
#include <fcntl.h>
#include <alloc.h>
#include <dos.h>
#include <dir.h>
#include <conio.h>
#include <ctype.h>
#include <time.h>
#include <string.h>
/* --------------------------------------------------------------------- */
/*
Some Valuable Definitions
*/
#define O_RAW O_BINARY /* Handle File as Binary */
#define TEMPORARY_FILENAME "CPR$.TMP" /* temporary file name (always)*/
#define MAJOR_VERSION 3 /* Current Software Version # */
#define MINOR_VERSION 0
#define BP 0x0C /* Form feed */
#define COMPRESSED 0x0F /* Compressed Print */
#define MAX_S 256 /* Maximum string length */
#define LENGTH 66 /* Default Page Length */
#define WIDTH 132 /* Default page width */
#define N_FILES 400 /* Maximum number of files */
#define TOC_LEN 1024 /* Max Table of Contents entries*/
#define MAX_FNAME_SIZE 25 /* Max filename length in response file */
#define MAX_HDR_BYTES 500 /* Max bytes in header file */
#define HEADER_SIZE 3 /* Header is 3 lines big */
/* -------------------------------------------------------------------------
/* These Macros are used to determine valid characters for Table of Contents
*/
/* returns true if letter, digit, '_' or ' '*/
#define isidchr(c) (isalnum(c) || (c == '_') || (c == ' '))
/* returns true if letter, digit, '_', '*', '\t' or '\n' */
#define isiechr(c) (isidchr(c) || c=='*' || c=='\t' || c=='\n')
/* --------------------------------------------------------------------- */
/*
Internal Program Function Prototypes
*/
int c_break(void); /* Called when BREAK is hit */
int file_stats(char *); /* File Statistics function */
char *Rs(); /* Strips trailing blanks from string */
char *EndComment(); /* Process string until end of comment */
char *EndString(); /* Process string until end of quoted string */
char *expand(); /* Process string expanding TABS to Spaces */
char *substr1();
/* -------------------------------------------------------------------- */
/*
Global Variables
*/
FILE *TempFile; /* Program Temporary File */
FILE *File; /* Current File being worked on */
FILE *Rfile; /* Response File handle */
FILE *Hfile; /* Header File handle */
struct ffblk fblock; /* struct used for calculating file size */
struct dfree disk_space; /* struct used for finding free disk space */
char file_time_buff[20]; /* file time is placed here */
char file_date_buff[20]; /* file date is placed here */
int Braces; /* Keeps track of brace depth */
int LineNumber; /* Count output lines */
int PageNumber = 1; /* You figure this one out */
int SectionNumber = 1; /* and this one to */
int PageLength = LENGTH; /* Normal paper length */
int PageWidth = WIDTH; /* normal page width */
int OnePerPage = 0; /* non-zero puts 1 function/page */
int NumLines = 0; /* non-zero puts line # in file */
int Number = 1;
int WantSorted = 1; /* Sort the table of contents */
int PageEnd; /* Accounts for space at bottom */
int InComment; /* Indicates if inside Comment */
int InString; /* Indicates if inside String */
int double_strike; /* # of times + 1 to write filename */
int header_flag; /* non-zero enables print codes/Dates/Page #'s */
int header_lines; /* number of extra lines from header file */
int extra_lines; /* non-zero enables extra lines after functions */
int table_contents; /* non-zero indicates Table of Contents Only */
int sectionflg; /* non-zero indicates print by section */
unsigned long memfree; /* amount of local memory left for file buffer */
char *TempName; /* pointer to temporary filename */
char *fname[N_FILES]; /* file names to be worked on */
char *STDIN = "\n"; /* special string pointer value to */
/* flag a file as being stdin */
char *Name; /* Current file name */
char *ProgName; /* This programs Path and Name */
char *Toc[TOC_LEN]; /* pointers to files in TOC */
int TocPages[TOC_LEN]; /* page numbers */
int TocCount; /* index into TOC arrays */
char header_buffer[MAX_HDR_BYTES];/* 500 byte buffer for user defined Page Headers */
char FunctionName[100]; /* Work area for parsing Func names */
char Todayv[45]; /* Today's Time and Date */
/* --------------------------------------------------------------------- */
/*
The filenames[N_FILES][25] array allocates an array capable of holding
N_FILES filenames that are up to 25 characters long.
Each filename in DOS can be 12 characters long and the response file
has a CRLF with each line and we also need a terminating zero byte
bringing the count up to 15. MAX_FNAME_SIZE bytes are provided for a
possible path
*/
/* --------------------------------------------------------------------- */
char filenames[N_FILES][MAX_FNAME_SIZE]; /* files read from response file */
/* --------------------------------------------------------------------- */
/*
** The following string is the definition of tab stops. Every 'T' is a
** tab, any other character is not. It is currently defined as a tab
** every 4 spaces. The comment below helps if you want to modify this,
** each row being 0+n, 50+n, 100+n, and 150+n, where n is the number
** above the declaration. Don't try to number each row with a comment,
** because you'll notice that the '\'s make it one big string.
*/
char *TabDef = "\
---T---T---T---T---T---T---T---T---T---T---T---T--\
-T---T---T---T---T---T---T---T---T---T---T---T--T-\
---T---T---T---T---T---T---T---T---T---T---T---T--\
-T---T---T---T---T---T---T---T---T---T---T---T---T";
/* ------------------------------------------------------------------------ */
/*
/* Program Instructions (Note the %??? arguments)
/*
*/
char option_list[] = "\n\
----------------------------- VERSION %d.%d SWITCHES ------------------------\n\
-@* Replace * with Response Filename (1 filename per line )\n\
-a* Replace * with Drive Wildcard\n\
-c Printer Codes/Dates/Page #'s off (default is Enabled )\n\
-d Double Strike Printing Enabled (default is Disabled )\n\
-h* Replace * with Header Filename\n\
-l## Replace ## with PageLength (default = %3d )\n\
-n Numbers Source Lines (Resets to 1 w/each file)\n\
-o Places 1 function on a Page (default is multiple )\n\
-p* Replace * with starting Page Number\n\
-q* Replace * with starting Section Number\n\
-s Sort Table of Contents by Page # (default is Func. Name )\n\
-t Print Table of Contents Only (-t- suppress's Table )\n\
-w## Replace ## with Width (default = %3d )\n\
-x Enables Extra Lines after Functions (default is Disabled )\n\
[...] Means multiple filenames may be listed\n\n\
Response Files should have 1 filename per line up to %d \n\
characters followed by 1 CRLF and may contain up to %d filenames. \n\n\
Header Files contain the Strings to Print at the top of \n\
every page of the listing, entire file can be up to %d bytes.";
/* -------------------------------------------------------------------- */
/*
It all Starts With MAIN
*/
main(argc, argv)
int argc;
char **argv;
{
unsigned long int total_disk_free = 0;
unsigned char ch;
register int i;
int nextf = 0; /* index into fname[] */
long thetime;
ctrlbrk(c_break); /* set control-break handler */
double_strike = 1; /* default to no double strike */
header_flag = 1; /* default to codes and headers */
header_lines = 0; /* no extra lines from header file */
extra_lines = 0; /* no extra lines after functions */
ProgName = argv[0]; /* grab pointer to the programs name */
time(&thetime); /* grab the DOS time and date */
strcpy(Todayv,ctime(&thetime)); /* convert to ascii (LF at END OF STRING) */
strtok(Todayv,"\n"); /* strip the annoying LF off */
if (argc == 1) /*if only the program name given */
Usage(); /* if no args, show instructions */
for (i = 1; i < argc; i++) { /* other parse command line */
if (argv[i][0] == '-') { /* check for switch flag "-" */
switch (toupper(argv[i][1])) { /* and go thru the switches */
case '@': /* Response file */
nextf = ReadResponseFile(argv[i]);
break;
case 'A': /* "*.???" Print all specified files */
nextf = StarDot(argv[i]);
break;
case 'C': /* Print codes/Dates/Time and page # */
header_flag = 0;
break;
case 'D': /* Double Strike function names */
double_strike = 3;
break;
case 'H': /* Header file */
ReadHeaderFile(argv[i]);
break;
case 'L': /* Number of lines per page */
if ( ! argv[i][2]) { /* if -L ?? (ie.. a space) */
if (++i >= argc) /* see if another argument */
Usage(); /* if no then print Help */
if ( ! isdigit (argv[i][0])) /* is it a number? */
Usage(); /* No! Print Help */
PageLength = atoi (argv[i]); /* assign number */
}
else { /* Switch came as -L?? form (with no space) */
if (!isdigit(argv[i][2])) /* is it a number? */
Usage(); /* No! Print Help */
PageLength = atoi(&argv[i][2]); /* assign number */
}
break;
case 'N': /* Number Source Lines */
NumLines = 1;
break;
case 'O': /* 1 function per page */
OnePerPage = 1;
break;
case 'P': /* Starting Page Number */
if ( ! argv[i][2]) { /* if -P ?? (ie.. a space) */
if (++i >= argc) /* see if another argument */
Usage(); /* if no then print Help */
if ( ! isdigit (argv[i][0])) /* is it a number? */
Usage(); /* No! Print Help */
PageNumber = atoi (argv[i]); /* assign number */
}
else { /* Switch came as -P?? form (with no space) */
if (!isdigit(argv[i][2])) /* is it a number? */
Usage(); /* No! Print Help */
PageNumber = atoi(&argv[i][2]); /* assign number */
}
break;
case 'Q': /* Print by Section */
if ( ! argv[i][2]) { /* if -Q ?? (ie.. a space) */
if (++i >= argc) /* see if another argument */
Usage(); /* if no then print Help */
if ( ! isdigit (argv[i][0])) /* is it a number? */
Usage(); /* No! Print Help */
SectionNumber = atoi (argv[i]); /* assign number */
}
else { /* Switch came as -Q?? form (with no space) */
if (!isdigit(argv[i][2])) /* is it a number? */
Usage(); /* No! Print Help */
SectionNumber=atoi(&argv[i][2]);/* assign number */
}
sectionflg = 1;
break;
case 'S': /* Sorted Table of Contents */
WantSorted = 0;
break;
case 'T': /* Print Table of Contents Only */
table_contents = 1; /* enable flag */
if( argv[i][2] == '-') /* if disabling TOC */
table_contents = -1;/* disable it */
break;
case 'W': /* Page Width */
if ( ! argv[i][2]) { /* if -W ?? (ie.. a space) */
if (++i >= argc) /* see if another argument */
Usage(); /* if no then print Help */
if ( ! isdigit (argv[i][0])) /* is it a number? */
Usage(); /* No! Print Help */
PageWidth = atoi (argv[i]); /* assign number */
}
else { /* Switch came as -W?? form (with no space) */
if (!isdigit(argv[i][2])) /* is it a number? */
Usage(); /* No! Print Help */
PageWidth = atoi(&argv[i][2]); /* assign number */
}
break;
case 'X': /* Extra Lines after Functions */
extra_lines = 1;
break;
case '\0': /* End of string?(out of enviroment) */
if (nextf >= N_FILES) {
fprintf (stderr, "%s: too many files\n", argv[0]);
exit (1);
}
fname[nextf++] = STDIN; /* any in excess goes to STDIN */
break;
default: /* No arguments given */
Usage(); /* show program instructions */
break;
}
}
else { /* Argument (argv[i]) wasn't a switch parmeter */
if (nextf >= N_FILES) {
fprintf (stderr, "%s: too many files\n", argv[0]);
exit (1);
}
fname[nextf++] = argv[i]; /* copy pointer to filename */
}
}
if ( ! nextf) /* No files were specified */
fname[nextf++] = STDIN; /* so use STDIN as the input file */
PageEnd = PageLength - (1 + PageLength / 20);
StartTempFile(); /* open temporary file */
for (i = 0; i < nextf; i++) { /* walk thru file list */
if (fname[i] == STDIN) { /* if no files */
File = stdin; /* assign stdin as input */
Name = "Standard Input"; /* assign name for printout */
fprintf(stderr,"Accepting Input from STDIN, ^Z to END\n");
}
else { /* there was a filename */
if( (File = fopen( Name = fname[i], "r" )) == NULL ) {
fprintf (stderr, "%s: Can't open file \"%s\"\n",
ProgName, Name );
continue; /* keep going if not found */
}
else { /* file opened OK so read */
fprintf(stderr, "\nReading File #%3d of %3d: \" %s \"",
i+1, nextf, fname[i]);
memfree = coreleft(); /* compute amount of free memory */
memfree = ( (memfree > 32767L) ?/* if to much memory then */
32767L : /* set max for setvbuf */
memfree ); /* else take as much as u can*/
if( setvbuf(File, NULL, _IOFBF, (int) memfree) != 0) {
fprintf(stderr,"Input Buffer failed to allocate.\n");
}
}
}
List(); /* Read File in and process data */
if (File != stdin) { /* if it's not STDIN */
fclose(File); /* close file & deallocate buffer */
}
}
if( PageNumber > 1 || LineNumber > 0 )
BreakPage();
EndTempFile(); /* Close Temporary File */
fprintf(stderr,"\n\n");
getdfree(0, &disk_space);/* find out free disk space after cpr$.tmp created */
total_disk_free = ( ( (long)disk_space.df_bsec * /* bytes per sector */
(long)disk_space.df_sclus) * /* sectors per cluster */
(long)disk_space.df_avail); /* clusters available */
findfirst(TEMPORARY_FILENAME,&fblock,0); /* read temp file size in */
if(fblock.ff_fsize >= total_disk_free) { /* see if copy can be output */
fprintf(stderr,"Insufficient Disk Space!\n\
\nMinimum of %lu bytes needed.\
\n%lu bytes are available\n\
\nDo You wish to continue? (Y/N)",
fblock.ff_fsize, total_disk_free);
do {
ch = (toupper(getche()) );
}
while((ch != 'Y') && (ch != 'N'));
if(ch != 'Y')
Done(); /* Delete Temporary File */
fprintf(stderr,"\n\n");
}
if((!table_contents) || /* if TOC and file enabled */
(table_contents == 1)) /* or TOC only enabled */
DumpTableOfContents(); /* Print Table of Contents */
if((!table_contents) || /* if TOC and file enabled */
(table_contents == -1)) /* or no TOC */
DumpTempFile(); /* then dump the file */
Done(); /* Clean things up and leave */
}
/*****************************************************************************/
Usage()
{
fprintf (stderr,"Usage: %s SWITCHES filename [...]",ProgName);
fprintf (stderr,option_list ,
MAJOR_VERSION, MINOR_VERSION, LENGTH, WIDTH,
MAX_FNAME_SIZE-1, N_FILES, MAX_HDR_BYTES);
exit(1);
}
/*****************************************************************************/
StartTempFile()
{
TempName = TEMPORARY_FILENAME; /* Temporary Filename */
if( (TempFile = fopen(TempName, "w")) == NULL ) {
fprintf (stderr, "%s: Can't open temp file!\n", ProgName);
exit(1);
}
}
/*****************************************************************************/
EndTempFile()
{
fclose (TempFile);
}
/*****************************************************************************/
DumpTempFile()
{
int fd,n;
char buff[1025];
if ((fd = open (TempName, O_RDONLY | O_RAW)) == -1) {
fprintf (stderr, "%s: can't open temp file\n", ProgName);
exit (1);
}
while ((n = read (fd, buff, 1024)) != 0) {
if (write (1, buff, n) == -1) {
fprintf (stderr, "%s: write error (1)\n", ProgName);
exit (1);
}
}
}
/*****************************************************************************/
Done()
{
if( TempName ) /* if you created a file */
unlink( TempName ); /* Delete temporary file */
exit(0); /* and leave the hard way */
}
/*****************************************************************************/
List() /* Process Incoming File */
{
register int bp;
char buffer[257];
if( sectionflg ) { /* if by section */
PageNumber = 1; /* Pages start at 1 */
LineNumber = 0; /* Lines reset each time */
}
NewPage(); /* bump page & output header */
NewFile();
bp = Braces = 0; /* no begin page and braces */
while( fgets(buffer, 256, File) != NULL ) { /* read a line upto 256 bytes*/
Rs(buffer); /* Remove Trailing Spaces */
if( bp ) /* if beginning page */
NewFunction(); /* setup for new function */
if( (LineNumber + 1) > PageEnd ) /* if going past page end */
NewPage(); /* start a new page */
if(!Braces && LooksLikeFunction(buffer)) /* no braces and a function */
AddToTableOfContents(); /* then add to TOC */
bp = PutLine(buffer);
LineNumber++;
}
if( sectionflg ) /* if by sections */
SectionNumber ++; /* Bump to next Section */
}
/*****************************************************************************/
NewPage() /* Process New Page */
{
if( LineNumber > HEADER_SIZE ) {
if( PageNumber >= 0 ) {
PageNumber ++; /* bump Page Number */
}
BreakPage(); /* form feed if allowed */
LineNumber = 0; /* set flag for a header */
}
if( LineNumber == 0 ) /* Each new page */
PutHeader(); /* Outputs a Header */
}
/*****************************************************************************/
NewFile()
{
register int i, l;
char temp[80];
if (TocCount >= TOC_LEN) {
fprintf (stderr, "%s: too many table of contents entries\n", ProgName);
exit (1);
}
if( (Toc[TocCount] = (char *) malloc(130)) == NULL) /* allocate some memory */
ReportMemoryError();
sprintf (Toc[TocCount], "\n\tFile: %s ", Name); /* to put filename into */
l = strlen(Toc[TocCount]) - 1; /* and findout how long it is */
if( l < 64 ) { /* if not to long */
i = (64 - l) / 8; /* calc. TAB increment */
for( l=0; l < i; ++l ) /* keep within 64 columns */
strcat(Toc[TocCount],"\t"); /* and put some TAB's out */
}
file_stats(Name); /* findout file stats */
if(! sectionflg ) {
sprintf (temp, " Page %4d (%s %s)\n", /* Page #, Time & date */
PageNumber, file_date_buff, file_time_buff);
}
else {
sprintf (temp, " Section %4d (%s %s)\n", /* Section, Time & Date*/
SectionNumber, file_date_buff, file_time_buff);
}
strcat(Toc[TocCount], temp); /* copy to main buffer */
++ TocCount; /* bump the entries */
if (NumLines) /* if numbering lines */
Number = 1; /* reset linenumber */
InComment = InString = 0; /* not in comment or string */
}
/****************************************************************************/
PutLine(l)
register char *l;
{
register char c;
int bp;
char *save;
char *section, *p;
int offset;
char Digits[15];
int Size;
int pos;
bp = 0;
for( save = expand(l);
( (c = *l) != 0);
++l ) { /* bump thru the string */
if( InComment ) /* if your in a comment */
l = EndComment(l); /* process till your out */
else
if( InString ) /* if your in a string */
l = EndString(l); /* process till your out */
else
switch(c) { /* it must be something */
case '{': /* curly brace IN */
++Braces; /* increment brace count */
break;
case '}': /* curly brace OUT */
if( --Braces == 0) /* coming out yet? */
if (*(l+1) == ';') /* is it structure? */
++l; /* continue thru string */
else
if(extra_lines) /* if option enabled */
bp = 1; /* flag for extra lines */
break;
case '\'': /* Forward Slash */
++l; /* continue thru string */
break;
case '"': /* Quotation Mark */
InString = 1; /* must be in a string */
break;
case '/': /* Start of Comment */
if( *(l+1) == '*' ) { /* is next character * ? */
InComment = 1; /* must be in a comment */
++l; /* continue thru string */
}
break;
}
}
if (NumLines) { /* if line numbering enabled */
sprintf (Digits,"[%d] ", Number); /* make a string */
Size = strlen(Digits); /* calc. its size */
}
else {
Size = 0; /* else it's size is 0 */
}
if (strlen(save) + /* if original strings size */
Size > /* and the size of numbers */
PageWidth) { /* are bigger than the width */
section = substr1(save, 0, PageWidth - Size);
if (section[strlen(section) - 1] != ' ')
if (NULL == (p = strrchr(section, ' ')))
offset = strlen(section);
else
offset = p - section;
else
offset = strlen(section) - 1;
section[offset] = NULL;
if (NumLines) { /* if line numbering is enabled */
fprintf (TempFile, "[%d] %s\n", Number++, section);
}
else {
fprintf (TempFile, "%s\n", section);
}
pos = offset + 1;
do {
section = substr1(save, pos, pos + PageWidth - 8);
if (strlen(save) - pos + 8 > PageWidth)
if (section[strlen(section) - 1] != ' ')
if (NULL == (p = strrchr(section, ' ')))
offset = strlen(section);
else
offset = p - section;
else
offset = strlen (section) - 1;
else
offset = strlen(section);
section[offset] = NULL;
/** ----------------------------------------------------------------- **/
/* Removed this for some reason
/*
/* if (section[strlen(section) - 1] == '\n')
/* section[strlen(section) - 1] = NULL;
*/
/* Line is to long for pagewidth so continue on next line */
fprintf (TempFile, "C %s\n", section);
if (++LineNumber > PageEnd)
NewPage();
}
while ((pos += offset + 1) < strlen(save));
}
else {
if (NumLines) /* if line numbering enabled */
fprintf (TempFile, "[%d] %s\n", Number++, save);
else
fprintf (TempFile, "%s\n", save);
}
return(bp);
}
/*****************************************************************************/
NewFunction() /* Process New Function */
{
register int i;
if( LineNumber > (PageLength * 3 / 4) ) /* 49.5 lines */
NewPage();
else {
if (!OnePerPage) { /* if mult. functions per page */
for( i=0; i < (PageLength/7); ++i )
putc ('\n', TempFile); /* add extra lines */
LineNumber += PageLength/7; /* set line counter also */
}
else
NewPage(); /* otherwise its 1 func. per page*/
}
}
/*****************************************************************************/
BreakPage() /* Process Page Break */
{
if(header_flag) /* if its allowed send a FORM FEED */
putc (BP, TempFile);
}
/*****************************************************************************/
PutHeader()
{
register int i, l, j;
if(header_flag) /* if its allowed send a COMPRESSED Code */
putc (COMPRESSED, TempFile);
putc ('\n', TempFile);
if(header_flag ) { /* if its allowed send out the HEADER */
l = strlen(Name); /* Filename or Table of Contents label length */
for( j=0; j < double_strike; ++j) {
fprintf (TempFile, "%s", Name); /* Write out Filename or TOC */
if( (j < 2) && (double_strike == 3) )
putc('\r', TempFile); /* Provide for Double Strike CR */
}
if( PageNumber > 0 ) { /* if your not on the TOC pages */
for( i = (l+7)/8; i < 6; ++i )
putc ('\t', TempFile); /* Tab out for position */
if(! sectionflg ) {
fprintf (TempFile, "%s\tPage: %d\n\n\n", Todayv,PageNumber);
}
else {
fprintf (TempFile, "%s\tSection %3d - %d\n\n\n",
Todayv,SectionNumber,PageNumber);
}
if(header_lines) /* Header for TOP OF PAGE */
fprintf (TempFile, "%s", header_buffer);
}
else { /* 1st line of Table of Contents page gets the time and date */
for( i = (l+7)/8; i < 6; ++i ) /* Tab out for time/date */
putc ('\t', TempFile);
fprintf (TempFile, "%s\n\n", Todayv); /* Todays Time and Date */
if(header_lines) /* Header for TOP OF PAGE */
fprintf (TempFile, "%s", header_buffer);
}
}
LineNumber += (HEADER_SIZE + header_lines); /* bump line number counter */
}
/*****************************************************************************/
LooksLikeFunction(s)
register char *s;
{
register char *p;
char *save;
int Cnt, nosl,nolp,norp,flg;
char Digits[15];
int AddOne = 0;
if( InComment || InString) /* if your in a comment or in a string */
return(0); /* just leave and return 0 */
p = FunctionName; /* assign pointer to function name string */
save = s; /* save address of string */
nosl = nolp = norp = 0; /* no left or right paren or no slash */
flg = 1;
for(; *s && flg ; s++) { /* go until end of string or flag is set */
switch (*s) { /* switch on each character in string */
case '(': /* is it a left paren? */
if (!nolp) { /* if no left paren already */
nolp = 1; /* flag that you've got one */
/* 3/4/87 added following line to include ARGS in TOC */
*p++ = *s; /* move byte of ARG into function buffer */
}
else
return(0); /* or return if you've already had one */
break;
case ')': /* is it a right paren? */
if (nolp && !norp) {/* if already a left paren and no right yet */
norp = 1; /* flag that you've got a right paren */
/* 3/4/87 added following line to include ARGS in TOC */
*p++ = *s; /* move byte of ARG into function buffer */
}
else
return(0); /* or return if conditions were'nt right */
break;
default: /* everything comes thru here */
if (!nolp) { /* if no left paren yet */
if (isiechr(*s)) { /* is it alpha,digit,'_*\t\n'? */
if (isidchr(*s))/* is it alpha,digit,'_' or ' '? */
*p++ = *s; /* if it is store the byte for TOC */
else
p = FunctionName; /* start over if '*\t\n' & nolp */
break;
}
else
return(0); /* return if conditions weren't right */
}
if (!norp) { /* if no right paren yet */
if (isiechr(*s) || *s == ',') { /* is it alpha,digit,'_ *\t\n'?*/
/* 3/4/87 added following line to include ARGS in TOC */
*p++ = *s; /* move byte of ARG in function buffer */
break;
}
else
return(0); /* return if conditions weren't right */
}
if (Cmemb(*s," \t\n\r") && !nosl) /* is it ' \t\n\r' or no slash yet */
break;
if (*s == '/' && !nosl) { /* is it a '/' and no slash yet */
nosl = 1; /* flag that you've got one */
break;
}
if (*s == '*' && nosl) { /* if its '*' & you got a slash already */
flg = 0; /* set flag to abort loop */
break;
}
return(0); /* return if conditions not right */
} /* end of switch */
} /* end of for loop */
if (nolp != 1) /* return if no left paren found */
return(0);
*p = '\0'; /* else terminate function buffer */
if (NumLines) { /* if line numbering enabled */
sprintf (Digits,"[%d] ", Number); /* format number into string */
Cnt = strlen(Digits) + AddOne;
while (Cnt-- > 0)
putc (' ', TempFile);
AddOne = 0;
}
/*
* This will cause the function name part of the line to
* be double striken.
*/
if( double_strike == 3) {
while (*save && *save != '(') /* double strike up to func name */
putc (*save++, TempFile);
putc ('\r', TempFile); /* use CR for doublestrike */
}
return(1);
}
/****************************************************************************/
AddToTableOfContents()
{
register int l;
register char *p;
if (TocCount >= TOC_LEN) {
fprintf (stderr, "%s: too many table of contents entries\n", ProgName);
exit (1);
}
l = strlen(FunctionName); /* find how long name is */
p = Toc[TocCount] = (char *) malloc(l+1); /* allocate just enough memory */
if( p == NULL) /* did it really allocate */
ReportMemoryError(); /* No! then report error */
strcpy(p, FunctionName); /* copy the name to new space */
TocPages[TocCount] = PageNumber; /* plug the page number in */
++TocCount; /* bump the count */
}
/****************************************************************************/
DumpTableOfContents()
{
register int i, j, l;
if( TocCount == 0 ) /* if there nothing to print */
return; /* then just return */
if (WantSorted) /* if you wanted it sorted by page number */
SortTableOfContents(); /* then we must sort it first */
Name = "Table of Contents"; /* give me a title for the page */
PageNumber = -1; /* Table of Contents pages are not numbered */
LineNumber = 0; /* and neither are the lines */
TempFile = stdout; /* default output to standard out */
NewPage(); /* start out creating a new page */
for( i=0; i < TocCount; ++i ) {
if( Toc[i][0] == '\n' ) {
if( (LineNumber + 5) > PageEnd )
NewPage();
printf("%s", Toc[i]);
LineNumber += 2;
continue;
}
if( ++LineNumber > PageEnd )/* if going off end of page */
NewPage(); /* start a new page */
printf("\t\t%s ", Toc[i]); /* print func. name in TOC */
l = strlen(Toc[i]); /* length if function name with parms */
for( j=l; j < 48; ++j ) /* put dots out to column 48 */
putchar('.'); /* put dots out to page num. in TOC */
printf(" %d\n", TocPages[i]); /* print page number for function */
}
if(header_flag) /* if control codes are allowed */
putchar(BP); /* print a Form Feed */
else
putchar('\n'); /* otherwise its a New Line */
fflush(stdout); /* make sure everything is written out */
}
/****************************************************************************/
/*
Sort Table of Contents by Page number rather than function name
*/
SortTableOfContents()
{
register int i, tempint;
char *tempchar;
int flag;
do {
flag = 0; /* default to already sorted */
for (i = 0; i < TocCount - 1; i++) { /* look at them all */
if (Toc[i][0] == '\n' || Toc[i+1][0] == '\n')
continue; /* don't sort across file names */
if (strcmp (Toc[i], Toc[i+1]) > 0) {/* compare the strings */
tempchar = Toc[i]; /* copy to temp pointer */
Toc[i] = Toc[i+1]; /* swap the pointers in array */
Toc[i+1] = tempchar; /* put the temp pointer back */
tempint = TocPages[i]; /* grab the page number */
TocPages[i] = TocPages[i+1]; /* swap page numbers */
TocPages[i+1] = tempint; /* put the temp page number back */
flag = 1; /* indicate you've swapped */
}
}
}
while (flag); /* go until no more swaps can be made */
}
/****************************************************************************/
char *EndComment(p) /* Process string until you come out of COMMENT */
register char *p;
{
register char c;
while( (c = *p++) != 0 ) /* while there are chars to look at */
if( c == '*' && *p == '/' ) { /* and there a splat or a slash */
InComment = 0; /* say your not in the comment */
break; /* and leave the loop */
}
return(p-1); /* returning the new pointer addr. */
}
/*****************************************************************************/
char *EndString(p) /* Process string until you come out of STRING */
register char *p;
{
register char c;
while( (c = *p++) != 0 ) /* while there are chars to look at */
if( c == '\\' ) { /* and forward slashs for next line */
continue; /* means "Just read on McDuck" */
}
else if( c == '"' ) { /* if you found the ending quote */
InString = 0; /* say your not in a string anymore */
break; /* and leave the loop */
}
return(p-1); /* returning the new pointer addr. */
}
/****************************************************************************/
/*
* This is the function substr1(). The calling sequence is:
*
* substr1(string, startpos, endpos).
*
* The function returns a pointer to a static string (written over -
* on subsequent calls) which is a substring of the string `string'
* starting at `startpos' (the first position is 0 (zero)) and ending
* at `endpos' (non-inclusive). All arguments must be present or
* strange things happen with the system stack.
*
* An example of the use is:
*
* x = substr1(string, 2, 5);
* (where string == "This is a test.")
*
* This call returns a pointer to:
* "is "
* An error code of -1 is returned is the `endpos' is greater than
* `startpos'
*
* Lance E. Shepard
*/
char *substr1(string, start, end)
char *string;
int start;
int end;
{
static char retstr[MAX_S];
int loop1;
int loop2;
if (end < start) {
exit(-1);
}
for (loop2 = 0; loop2 < MAX_S; loop2++)
retstr[loop2] = NULL;
for (loop1 = start, loop2 = 0; string[loop1] != NULL &&
loop1 < end && loop2 <= MAX_S; loop1++, loop2++)
retstr[loop2] = string[loop1];
retstr[++loop2] = NULL;
return(retstr);
}
/****************************************************************************/
/*
* This is the function `char *expand().' This function takes as
* an argument a NULL terminated string and replaces all occurances
* of the tab character with 8 (eight) spaces. The function returns
* a pointer to a static string which is overwritten on subsequent
* calls.
*/
/****************************************************************************/
char *expand(string)
char *string;
{
int count;
static char retstr[MAX_S];
for (count = 0; count < MAX_S; retstr[count++] = NULL)
;
for (count = 0; *string != NULL; count++, string++) {
if (*string == '\t') {
retstr[count] = ' ';
/* while (((count + 1) % 8) != 0) */
while (TabDef[count] != 'T')
retstr[++count] = ' ';
}
else
retstr[count] = *string;
}
retstr[count] = NULL;
return(retstr);
}
/****************************************************************************/
char *Rs(s) /* strip trailing blanks from string */
char s[];
{
int n;
for (n=strlen(s)-1 ; n >= 0 && isspace(s[n]) ; n--)
; /* find the last space in the string */
s[n+1] = '\0'; /* plop a null char on top of it */
return(s); /* return pointer to string */
}
/****************************************************************************/
int Cmemb(a,b) /* is character "a" a member of string "b" */
char a, *b;
{
while (*b) /* go until the null character */
if (a == *b++) /* looking for the character and bumping the pointer */
return(1); /* returning 1 if its found */
return( (!a) ? 1 : 0 ); /* return 0 if "a" was a non-zero character */
}
/****************************************************************************/
StarDot(file_string)
char * file_string;
{
extern char filenames[N_FILES][MAX_FNAME_SIZE];
extern char fnames[N_FILES];
extern struct ffblk fblock;
extern struct dfree disk_space;
unsigned long int total_file_size = 0;
unsigned long int total_disk_free = 0;
int done;
int i = 0;
file_string += 2; /* bump past -A switch */
if( (done = findfirst(file_string,&fblock,0)) != 0) {/* Attempt 1st file read */
fprintf(stderr,"No Files Found\n");
exit(1);
}
while(!done && i < N_FILES) { /* go until done or to many files */
strcpy(&filenames[i][0],fblock.ff_name);/* copy names into array */
fname[i] = &filenames[i++][0]; /* copy pointer to name */
total_file_size += fblock.ff_fsize; /* keep running total of filesizes */
done = findnext(&fblock); /* read next availables file info */
}
if( i == N_FILES)
fprintf(stderr,"Printing ONLY 1st %d Files\n", N_FILES);
getdfree(0, &disk_space); /* find free disk space */
total_disk_free = ( ((long)disk_space.df_bsec * /* convert to bytes */
(long)disk_space.df_sclus) *
(long)disk_space.df_avail);
if((total_file_size * 2) >= total_disk_free) {
fprintf(stderr,"Insufficient Disk Space!\nMinimum of %lu bytes needed.\
\nYou Have %lu bytes free\n",
total_file_size * 2, total_disk_free);
exit(1);
}
return(i); /* return new number of files */
}
/*****************************************************************************/
ReportMemoryError()
{
fprintf(stderr,"Memory Allocation Error\n");
if( TempName ) { /* if there is a file to work on */
EndTempFile(); /* Make sure file is closed */
unlink( TempName ); /* Delete temporary file */
}
exit(1);
}
/*****************************************************************************/
ReadHeaderFile(header_file)
char *header_file;
{
extern char header_buffer[MAX_HDR_BYTES];
extern int header_lines;
int ch;
int i = 0;
int x = 0;
char *string;
header_file += 2; /* strip the "-h" from the string */
if(( Hfile = fopen(header_file, "r")) == NULL) {
fprintf(stderr,"Can't Open Header File %s\n",header_file);
exit(1); /* terminate abruptly */
}
else {
/* read entire file that is up to MAX_HDR_BYTES characters long */
while( (ch = fgetc(Hfile)) != EOF) {
header_buffer[i++] = (unsigned char) ch;
if(i < MAX_HDR_BYTES)
continue;
else
break;
}
header_buffer[i] = '\0'; /* terminate buffer */
fclose(Hfile); /* and close the file */
for(x = 0, string = header_buffer; x <= i; x++) {
if(*string++ == '\n') /* count number of line feeds */
header_lines++; /* tell the NewPage Function */
}
}
}
/*****************************************************************************/
ReadResponseFile(response_file)
char *response_file;
{
char fpntr[80]; /* area for string to be read into */
extern char filenames[N_FILES][MAX_FNAME_SIZE];
extern char fnames[N_FILES];
extern struct ffblk fblock;
extern struct dfree disk_space;
unsigned long int total_file_size = 0;
unsigned long int total_disk_free = 0;
int i = 0;
response_file += 2; /* strip the "-@" from the string */
if(( Rfile = fopen(response_file, "r")) == NULL) {
fprintf(stderr,"Can't Open Response File %s\n",response_file);
exit(1); /* terminate abruptly */
}
else {
/* read a entire line from the Rfile that is up to 80 characters long */
while(fgets(fpntr,80,Rfile) != NULL && i < N_FILES) {
strtok(fpntr," \n"); /* strip to LF or space */
strcpy(&filenames[i][0],fpntr); /* copy names into array */
fname[i] = &filenames[i++][0]; /* copy pointer to name */
findfirst(fpntr,&fblock,0); /* read file size in */
total_file_size += fblock.ff_fsize; /* keep running total of filesizes */
}
fclose(Rfile); /* and close the file */
getdfree(0, &disk_space); /* find free disk space */
total_disk_free = ( ((long)disk_space.df_bsec * (long)disk_space.df_sclus) *
(long)disk_space.df_avail);
if((total_file_size * 2) >= total_disk_free) {
fprintf(stderr,"Insufficient Disk Space!\nMinimum of %lu bytes needed.\
\nYou Have %lu bytes free\n",
total_file_size * 2, total_disk_free);
exit(1);
}
return(i); /* return new number of files */
}
return(0);
}
/*****************************************************************************
This routine is executed when the CONTROL-BREAK key combination is hit
*****************************************************************************/
c_break()
{
fprintf(stderr,"Control-Break hit. Program aborting ...\n");
if( TempName ) { /* if you created a file */
EndTempFile(); /* Make sure file is closed */
unlink( TempName ); /* Delete temporary file */
}
return(0); /* ABORT sequence */
}
/*****************************************************************************/
file_stats(filename)
char *filename;
{
extern struct ffblk fblock;
findfirst(filename,&fblock,0); /* read data into structure */
/* ------------------- Show date in standard format --------------------*/
sprintf(file_date_buff,"%02d-%02d-%02d",
((fblock.ff_fdate >> 5) & 0x0f), /* month */
(fblock.ff_fdate & 0x1f) , /* day */
((fblock.ff_fdate >> 9) + 80 )); /* year */
/* ----------------- Show time in 12 Hour Format ------------------- */
if ( (fblock.ff_ftime >> 0x0b) <= 12)
{
sprintf(file_time_buff,"%02d:%02d",
(fblock.ff_ftime >> 0x0b),
((fblock.ff_ftime >> 5 ) & 0x3f )); /* minutes */
}
else
{
sprintf(file_time_buff,"%02d:%02d",
((fblock.ff_ftime >> 0x0b) - 12),
((fblock.ff_ftime >> 5 ) & 0x3f )); /* minutes */
}
/* ------------------ Decipher whether its AM or PM ---------------- */
if ( (fblock.ff_ftime >> 0x0b) < 12)
strcat(file_time_buff," am"); /* for AM */
else
strcat(file_time_buff," pm"); /* for PM */
}
/*************************************************************************/